package com.uml.umlwork.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.uml.umlwork.config.security.JWTFactory;
import com.uml.umlwork.dto.user.UpdateUserDTO;
import com.uml.umlwork.dto.user.UserSignUpDTO;
import com.uml.umlwork.entity.Student;
import com.uml.umlwork.entity.Teacher;
import com.uml.umlwork.entity.User;
import com.uml.umlwork.entity.enumeration.GenderEnum;
import com.uml.umlwork.entity.enumeration.RoleEnum;
import com.uml.umlwork.mapper.StudentMapper;
import com.uml.umlwork.mapper.TeacherMapper;
import com.uml.umlwork.mapper.UserMapper;
import com.uml.umlwork.service.UserService;
import com.uml.umlwork.utils.AESUtil;
import com.uml.umlwork.utils.SystemMsgJsonResponse;
import com.uml.umlwork.vo.user.UserInfoVO;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
 * @author Siki
 * @date 2020/12/21
 */
@Service
public class UserServiceImpl implements UserService {
    private final UserMapper userMapper;
    private final JWTFactory jwtFactory;
    private final TeacherMapper teacherMapper;
    private final StudentMapper studentMapper;

    public UserServiceImpl(UserMapper userMapper, JWTFactory jwtFactory, TeacherMapper teacherMapper, StudentMapper studentMapper) {
        this.userMapper = userMapper;
        this.jwtFactory = jwtFactory;
        this.teacherMapper = teacherMapper;
        this.studentMapper = studentMapper;
    }

    @Override
    public String login(String username, String password) {

        return Optional.ofNullable(
                userMapper.selectOne(new QueryWrapper<User>().eq("username", username))
        ).filter(user ->
                password.equals(AESUtil.decrypt(user.getPassword(), AESUtil.getAssetsDevPwdField()))
        ).map(jwtFactory::getToken)
                .orElseThrow(() ->
                        new RuntimeException("该username:" + username + "密码错误"));


    }

    @Override
    public void signUp(UserSignUpDTO dto) {
        // 查出结果代表数据库有这个数据
        Assert.isNull(userMapper.selectOne(new QueryWrapper<User>()
                .eq("username", dto.getUsername())), "用户名已存在");
        var user = new User();
        RoleEnum role = RoleEnum.valueOf(dto.getRole());
        user.setUsername(dto.getUsername())
                // 加密
                .setPassword(AESUtil.encrypt(dto.getPassword(),
                        AESUtil.getAssetsDevPwdField()))
                .setPhone(dto.getPhone())
                .setName(dto.getName())
                .setRole(role);
        userMapper.insert(user);
        switch (role) {
            case TEACHER:
                var teacher = new Teacher();
                teacher.setUserId(user.getId());
                teacherMapper.insert(teacher);
                break;
            case STUDENT:
                var student = new Student();
                student.setUserId(user.getId());
                studentMapper.insert(student);
                break;
            case ADMIN:
                break;
            default:
                ;
                // TODO: 2020/12/22 @siki: 管理员稍后处理
        }
    }

    @Override
    public SystemMsgJsonResponse updatePassword(UpdateUserDTO dto, String id) {
        Assert.isTrue(dto.getNewPassword().equals(dto.getAgainPassword()), "两次密码输入不相同");
        return Optional.of(userMapper.selectById(id))
                .filter(user -> dto.getOldPassword().equals(AESUtil.decrypt(user.getPassword(), AESUtil.getAssetsDevPwdField())))
                .map(user -> {
                    user.setPassword(AESUtil.encrypt(dto.getNewPassword(), AESUtil.getAssetsDevPwdField()));
                    userMapper.updateById(user);
                    return SystemMsgJsonResponse.success();
                }).orElseThrow(() -> new RuntimeException("旧密码输入错误"));
    }

    @Override
    public UserInfoVO getUserInfo(String id) {
        User user = userMapper.selectById(id);
        UserInfoVO vo = new UserInfoVO();
        switch (user.getRole()) {
            case STUDENT:
                Student student = studentMapper
                        .selectOne(new QueryWrapper<Student>().eq("user_id", id));
                vo.setAge(student.getAge())
                        .setEmail(student.getEmail())
                        .setGender(Optional.ofNullable(student.getGender())
                                .map(GenderEnum::getName).orElse(GenderEnum.MAN.getName()))
                .setPhone(user.getPhone());
                break;
            case TEACHER:
                Teacher teacher = teacherMapper
                        .selectOne(new QueryWrapper<Teacher>().eq("user_id", id));
                vo.setAge(teacher.getAge())
                        .setEmail(teacher.getEmail())
                        .setGender(Optional.ofNullable(teacher.getGender())
                                .map(GenderEnum::getName).orElse(GenderEnum.MAN.getName()))
                        .setPhone(user.getPhone());
                break;
            default:
                ;
        }
        return vo.setUsername(user.getUsername())
                .setRoleList(new ArrayList<>(Collections.singleton(user.getRole().toString())));
    }

}
